package org.lee.middle;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.BeanUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.lee.middle.annotation.LeeMiddle;
import org.lee.middle.config.StarterService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Method;

@Aspect
@Component
public class MiddleJointPoint {

    private Logger logger = LoggerFactory.getLogger(MiddleJointPoint.class);

    @Autowired
    private StarterService starterService;

    @Pointcut("@annotation(org.lee.middle.annotation.LeeMiddle)")
    public void aopPoint() {

    }

    @Around("aopPoint()")
    public Object doBusiness(ProceedingJoinPoint jp) throws Throwable {
        Method method = getMethod(jp);
        LeeMiddle middle = method.getAnnotation(LeeMiddle.class);
        String value = getFieldValue(middle.key(), jp.getArgs());
        logger.info("lee middle handler method: {} value: {}", method.getName(), value);
        if (null == value || "".equals(value)) {
            return jp.proceed();
        }
        String[] items = starterService.split(",");
        for (String item : items) {
            if (value.equals(item)) {
                return jp.proceed();
            }
        }
        // 拦截掉
        return returnObject(middle, method);
    }

    private Method getMethod(ProceedingJoinPoint jp) throws NoSuchMethodException {
        Signature signature = jp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        return getClass(jp).getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
    }

    private Class<? extends Object> getClass(ProceedingJoinPoint jp) {
        return jp.getTarget().getClass();
    }

    private Object returnObject(LeeMiddle leeMiddle, Method method) throws InstantiationException, IllegalAccessException, IOException {
        Class<?> retType = method.getReturnType();
        String json = leeMiddle.returnJson();
        if ("".equals(json)) {
            return retType.newInstance();
        }
        return new ObjectMapper().readValue(json, retType);
    }

    private String getFieldValue(String fieldName, Object[] args) {
        String fieldValue = null;
        for (Object arg : args) {
            try {
                if (null == fieldValue || "".equals(fieldValue)) {
                    fieldValue = BeanUtils.getProperty(arg, fieldName);
                } else {
                    break;
                }
            } catch (Exception e) {
                if (args.length == 1) {
                    return args[0].toString();
                }
            }
        }
        return fieldValue;
    }
}
